<?php
session_start();
require "lib/db.php";
require "lib/order-function.php";
require "lib/orderdetail-function.php";
require "lib/product-function.php";

 //ini_set('memory_limit', '1024M');
 ini_set('max_execution_time', 300); 

//get association rules by minsup and minconf
if(isset($_GET['minSup'])&&isset($_GET['minConf'])){
	$minSup = $_GET['minSup'];
	settype($minSup,"int");
	$minConf = $_GET['minConf'];
	settype($minConf,"int");
	
	//$sup = array();
	//$conf = array();
	
	//step 1 get input is all list ProductID by each order
	$input = getInput();
	//$input = array(array('A','B','C','D','E'),array('B','C','E'),array('A','D','E'),array('D','E'),array('A','B','C'));
	//var_dump($input);
	
	
	
	//step 2 make itemset
	$itemSet = array();
	$input_length = count($input);//get the numbers of order
	for($i=0;$i<$input_length;$i++){
		for($j=0;$j<count($input[$i]);$j++){
			if(isInArray($itemSet,$input[$i][$j])==false){
				//if item not in itemset, push into itemset
				array_push($itemSet,$input[$i][$j]);	
				
				//check out of memory
				if(checkOutOfMemmory()==false){
					echo "out of memmory";
					return;	
				}
			}
		}
	}
	//var_dump($itemSet);

	
	//step 3 make frequentItemset, ex: {A},{A,B},{A,B,C}...
	$frequentItemSet = array();
	$k = 1;
	$candidate = array();
	for($i=0;$i<count($itemSet);$i++){//missing ex: $i++ intead $i
		$temp = array();//to push value into array although it has 1 value, ex: {A}
		array_push($temp,$itemSet[$i]);
		if(checkOutOfMemmory()==false){
			echo "out of memmory";
			return;	
		}
		array_push($candidate,$temp);
		if(checkOutOfMemmory()==false){
			echo "out of memmory";
			return;	
		}	
	}
	//$candidate={{A},{B},{C},{D},{E}} with level 1
	//var_dump($candidate);
	
	//$parent = array();
			//array_push($parent,array('A','B','C','D','E'),array('B','C','E'),array('A','D','E'),array('D','E'),array('A','B','C'));
	//$child = array('A','C','B');
	//echo countChildArrayInParentArray($parent, $child);
		
	
	$continue = true;//set continue from C1, L1, C2, L2, C3, L3...
	while($continue){
		$large = array();
		for($i=0;$i<count($candidate);$i++){
			$c = countChildArrayInParentArray($input,$candidate[$i]);
			//if(round($c/$input_length,2)*100 >= $minSup){
			if($c*100 >= $input_length*$minSup){
				if(isInArray($frequentItemSet,$candidate[$i])==false){
					array_push($frequentItemSet,$candidate[$i]);
					if(checkOutOfMemmory()==false){
						echo "out of memmory";
						return;	
					}	
				}
				if(isInArray($large,$candidate[$i])==false){
					array_push($large,$candidate[$i]);
					if(checkOutOfMemmory()==false){
						echo "out of memmory";
						return;	
					}
				}
			}
		}
		if(count($large)<2){//if length of large array is 0 or 1, loop stop
			$continue = false;
			break;	
		}else{
			$k = $k+1;
			$candidate=array();
			for($i=0;$i<count($large);$i++){
				for($j=0;$j<count($large);$j++){
					$combine = combine2ArrayWithLength($large[$i],$large[$j],$k);
					if(!is_null($combine)){
						array_push($candidate,$combine);
						if(checkOutOfMemmory()==false){
							echo "out of memmory";
							return;	
						}	
					}
				}	
			}
		}
	}
	
	//var_dump($frequentItemSet);
	
	//step 4 make association rules: x=>y
	//$childs = getChildSets(array('A','B','C'));
	//echo count($childs);
	//var_dump($childs);
	
	$x = array();//antecedent
	$y = array();//consequense
	$s = array();//support
	$c = array();//confidence
	
	//default delete all data of associatin rule, antecedence and consequence table
	deleteAllAssocationRule();
	deleteAllAntecedence();
	deleteAllConsequence();
	
	for($i=0;$i<count($frequentItemSet);$i++){
		
		if(checkOutOfMemmory()==false){
			echo "out of memmory";
			return;	
		}
			
		if(count($frequentItemSet[$i])<2){
			continue;//pass new loop with frequent item set length 1, ex: {A}, no need to get rules	
		}
		$childSets = getChildSets($frequentItemSet[$i]);
		//var_dump($childSets );
		$child_length = count($childSets);
		//echo $child_length." ";
		//the move child and the choose child is corresponding with index (x) and (length of parent - 1-x)
		for($j=0;$j<$child_length;$j++){
			
			$tempsup = countChildArrayInParentArray($input,$frequentItemSet[$i]);
			//var_dump($frequentItemSet[$i]);
		
			//if($tempsup>0){
				//array_push($sup,$tempsup);
				
				$supX = countChildArrayInParentArray($input,$childSets[$j]);//missing $i instead $j
				//$supY = round(countChildArrayInParentArray($input,$childSets[$child_length-1-$j])/$input_length,2)*100;
				if($supX>0){
					if(round($tempsup/$supX,2)*100 >= $minConf){//missing round($minConf/100,2) instead $minConf
						
						//$tempconf = round($tempsup/$supX,2)*100;//mistake $tempsup, error when $supY
						//array_push($conf,$tempconf);
						
						array_push($x,$childSets[$j]);
						if(checkOutOfMemmory()==false){
							echo "out of memmory";
							return;	
						}	
						array_push($y,$childSets[$child_length-1-$j]);	
						if(checkOutOfMemmory()==false){
							echo "out of memmory";
							return;	
						}
						array_push($s,round($tempsup/$input_length,2)*100);	
						array_push($c,round($tempsup/$supX,2)*100);	
						
						/*
						//save association rule to database
						if(round($tempsup/$input_length,2)*100 >= 5 && round($tempsup/$supX,2)*100 >= 50){
							$ruleID = addAssociationRule("rule");//just save rule name as "rule" for temporary
							for($k=0;$k<count($childSets[$j]);$k++){
								addAntecedence($ruleID,$childSets[$j][$k]);
							}
							for($k=0;$k<count($childSets[$child_length-1-$j]);$k++){
								addConsequence($ruleID,$childSets[$child_length-1-$j][$k]);
							}
						}
						*/
						//save association rule to database
						if(round($tempsup/$input_length,2)*100 >= 5 && round($tempsup/$supX,2)*100 >= 35 && count($childSets[$j])==1 && count($childSets[$child_length-1-$j])==1){
							$ruleID = addAssociationRule($childSets[$j][0],$childSets[$child_length-1-$j][0]);
						}
					}
				}	
			//}
		}
		if(checkOutOfMemmory()==false){
			echo "out of memmory";
			return;	
		}	
	}
	
	//var_dump($x);
	//var_dump($y);
	
	//step 5 output associatio rule
	echo '<table width="100%" border="1" cellspacing="0">
          <tr>
            <th>Rules</th>
			<th>Support(%)</th>
			<th>Confidence(%)</th>
          </tr>';
	if(count($x)>0){
		for($i=0;$i<count($x);$i++){
			$associationRules = "";
			$delimiter = ",";
			$first = true;
			for($j=0;$j<count($x[$i]);$j++){
				if(!$first){
					$associationRules = $associationRules.$delimiter;	
				}
				$item = $x[$i][$j];
				$product = getProductByID($item);
				$p = mysql_fetch_array($product);
				$productName = $p['ProductName'];
				$associationRules = $associationRules.$productName;
				$first = false;	
			}
			$associationRules = $associationRules."=>";
			$first = true;
			for($j=0;$j<count($y[$i]);$j++){
				if(!$first){
					$associationRules = $associationRules.$delimiter;	
				}
				$item = $y[$i][$j];
				$product = mysql_fetch_array(getProductByID($item));
				$productName = $product['ProductName'];
				$associationRules = $associationRules.$productName;
				$first = false;	
			}
			echo '<tr>
					<td>'.$associationRules.'</td>
					<td>'.$s[$i].'</td>
					<td>'.$c[$i].'</td>
				 </tr>';	
		}
	}else{
		echo '<tr>
				<td colspan="3">Do not any rule</td>
			  </tr>';
	}
    echo   '</table>';
}


//get all productID of each order
function getInput(){
	$input = array();
	$listOrder = getAllOrder();
	while($order = mysql_fetch_array($listOrder)){
		$orderID = $order['OrderID'];
		settype($orderID,"int");
		//get all order detail by orderid
		$listOrderDetail = getListOrderDetailByOrderID($orderID);
		$temp = array();
		while($orderDetail = mysql_fetch_array($listOrderDetail)){
			$productID = $orderDetail['ProductID'];
			settype($productID,"int");
			array_push($temp,$productID);
			if(checkOutOfMemmory()==false){
				echo "out of memmory";
				return;	
			}	
		}
		array_push($input,$temp);
		if(checkOutOfMemmory()==false){
			echo "out of memmory";
			return;	
		}	
	}
	return $input;
}

//check item is in array or not
function isInArray($array, $value){
	$check = false;
	for($i=0;$i<count($array);$i++){
		if($array[$i] == $value){
			$check = true;
			break;
		}
	}
	return $check;
}

//count the number of child array in parent array happen
function countChildArrayInParentArray($parent, $child){
	$count = 0;
	for($i=0;$i<count($parent);$i++){
		$child_length = count($child);
		$temp_count = 0;
		for($j=0;$j<$child_length;$j++){
			for($k=0;$k<count($parent[$i]);$k++){
				if($child[$j]==$parent[$i][$k]){
					$temp_count++;	
				}
			}
		}
		if($temp_count==$child_length){
			$count++;	
		}
	}
	return $count;
}

//combine two array with length define before
function combine2ArrayWithLength($arr1,$arr2,$k){
	$result = array();
	for($i=0;$i<count($arr1);$i++){
		if(isInArray($result,$arr1[$i])==false){
			array_push($result,$arr1[$i]);
			if(checkOutOfMemmory()==false){
				echo "out of memmory";
				return;	
			}		
		}
	}
	for($i=0;$i<count($arr2);$i++){
		if(isInArray($result,$arr2[$i])==false){
			array_push($result,$arr2[$i]);	
			if(checkOutOfMemmory()==false){
				echo "out of memmory";
				return;	
			}	
		}
	}
	if(count($result) == $k){
		sort($result);
		return $result;	
	}else{
		return NULL;	
	}
}

//get all child set from parent set except empty set, and parent set
//two things should note:1. the last child of defined length has last group
//2. from group length 1 combine get group length 2
//from group length 1 combine with group length 2 to get group length 3
//from group length 1 combine with group length 3 to get group length 4
//...
function getChildSets($parent){
	$childSets = array();
	$origin = array();//set with length 1
	for($i=0;$i<count($parent);$i++){
		$temp = array();
		array_push($temp,$parent[$i]);	
		if(checkOutOfMemmory()==false){
			echo "out of memmory";
			return;	
		}	
		array_push($childSets,$temp);
		if(checkOutOfMemmory()==false){
			echo "out of memmory";
			return;	
		}		
		array_push($origin,$temp);	
		if(checkOutOfMemmory()==false){
			echo "out of memmory";
			return;	
		}	
	}
	$k=2;
	$temp=$origin;
	$continue = true;
	while($continue){
		
		$temp2 = array();
		for($i=0;$i<count($origin);$i++){
			for($j=0;$j<count($temp);$j++){
				$combine = combine2ArrayWithLength($origin[$i],$temp[$j],$k);
				if($combine!=NULL && isInArray($childSets,$combine)==false){//missing  isInArray($childSets,$combine)==false
					if(count($combine)<count($parent)){//to except the parent set
						array_push($childSets,$combine);
						if(checkOutOfMemmory()==false){
							echo "out of memmory";
							return;	
						}		
					}	
					array_push($temp2,$combine);
					if(checkOutOfMemmory()==false){
						echo "out of memmory";
						return;	
					}			
				}
			}	
		}
		if(count($temp2)<2){
			$continue = false;
			break;	
		}else{
			$k++;
			$temp = $temp2;
		}
	}
	return $childSets;
}

function checkOutOfMemmory(){
	if( memory_get_usage() > ini_get("memory_limit")*1024*1024){//ini_get("memory_limit") = 128M
		//echo "out of memmory";
		return false;
	}else{
		return true;	
	}
}

function addAssociationRule($antecedence,$consequence){
	$qr ="INSERT INTO `association-rule`(Antecedence,Consequence) VALUES('$antecedence','$consequence')";
	mysql_query($qr);
	return mysql_insert_id();
}

function deleteAllAssocationRule(){
	$qr ="DELETE FROM `association-rule`;";
	mysql_query($qr);
}

function addAntecedence($ruleID, $productID){
	$qr ="INSERT INTO `antecedence`(RuleID,ProductID) VALUES('$ruleID','$productID')";
	mysql_query($qr);
}

function deleteAllAntecedence(){
	$qr ="DELETE FROM `antecedence`;";
	mysql_query($qr);
}

function addConsequence($ruleID, $productID){
	$qr ="INSERT INTO `consequence`(RuleID,ProductID) VALUES('$ruleID','$productID')";
	mysql_query($qr);
}

function deleteAllConsequence(){
	$qr ="DELETE FROM `consequence`;";
	mysql_query($qr);
}


?>